//
//  TCCalendar.m
//  TCCalendarSelector
//
//  Created by 叮叮 on 2021/5/8.
//

#import "TCCalendar.h"
#import "TCCalendarCollectionViewCell.h"
#import "TCCalendarHeaderView.h"
#import "TCCalendarTipView.h"

@interface TCCalendar()<UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, TCCalendarTipViewDelegate>
/// 日历滚动视图
@property (nonatomic) UICollectionView *collectionView;
/// 所有数据源
@property (nonatomic) NSMutableArray *dataSource;
/// 月份数据源
@property (nonatomic) NSMutableArray *monthDataSource;
/// 年份展示视图
@property (nonatomic) TCCalendarTipView *tipView;
/// 年份数据
@property (nonatomic) TCCalendarDateModel *tipModel;
/// 是否是第一次选中
@property (nonatomic, assign) BOOL isFirstSelect;
/// 第一次选中的 indexPath
@property (nonatomic) NSIndexPath *firstIndexPath;
/// 第二次选中的 indexPath
@property (nonatomic) NSIndexPath *secondIndexPath;
/// 选择的起始日期
@property (nonatomic) TCCalendarDateModel *startDate;
/// 选择的结束日期
@property (nonatomic) TCCalendarDateModel *endDate;
/// 今天数据
@property (nonatomic) TCCalendarDateModel *today;
/// 数据加载图
@property (nonatomic, weak) UIActivityIndicatorView *indicatorView;
/// 隐藏后是否移除视图
@property (nonatomic) NSNumber *_removeOnHidden;
/// 遮罩视图
@property (nonatomic) UIButton *maskView;
/// 内容视图
@property (nonatomic) UIView *contentView;
/// 将日历以 map 形式保存，方便查找
@property (nonatomic) NSMutableDictionary *dateMap;
/// 日历
@property (nonatomic) NSCalendar *calendar;
/// 起始年份
@property (nonatomic, assign) NSInteger startYear;
/// 结束年份
@property (nonatomic, assign) NSInteger endYear;
@end

static UIColor *_todayColor = nil;

static UIColor *_selectedColor = nil;

@implementation TCCalendar

+ (UIColor *)todayColor {
    if (!_todayColor) {
        _todayColor = [UIColor redColor];
    }
    return _todayColor;
}

+ (void)setTodayColor:(UIColor *)todayColor {
    _todayColor = todayColor;
}

+ (UIColor *)selectedColor {
    if (!_selectedColor) {
        _selectedColor = [UIColor lightGrayColor];
    }
    return _selectedColor;
}

+ (void)setSelectedColor:(UIColor *)selectedColor {
    _selectedColor = selectedColor;
}

- (BOOL)removeOnHidden {
    if (__removeOnHidden) {
        return [__removeOnHidden boolValue];
    } else {
        return YES;
    }
}

- (void)setRemoveOnHidden:(BOOL)removeOnHidden {
    __removeOnHidden = [NSNumber numberWithBool:removeOnHidden];
}

- (void)show {
    if (self) {
        self.hidden = NO;
        [self animateShow];
    }
}

- (NSCalendar *)calendar {
    if (!_calendar) {
        _calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    }
    return _calendar;
}

- (instancetype)init
{
    self = [super init];
    if (self) {
        [self initDataSource];
        [self setupUI];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self initDataSource];
        [self setupUI];
    }
    return self;
}

- (void)didMoveToSuperview {
    [super didMoveToSuperview];
    self.frame = self.superview.bounds;
    self.contentView.center = self.center;
    self.maskView.frame = self.superview.bounds;
}

/// 初始化日历数据
- (void)initDataSource {
    /// 异步加载数据，完成后刷新视图
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSDate *now = NSDate.date;
        
        NSDateComponents *comps = [self.calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond|NSCalendarUnitWeekday fromDate:now];
        NSInteger toYear = comps.year;
        self.startYear = toYear - 10;
        self.endYear = toYear + 10;
        
        NSMutableArray *monthDataSource = [NSMutableArray array];
        self.dataSource = [self datesArrayByStartYear:self.startYear endYear:self.endYear];
        for (TCCalendarDateModel *yearModel in self.dataSource) {
            [monthDataSource addObjectsFromArray:yearModel.dates];
        }
        
        self.monthDataSource = monthDataSource;
        [self initDateMap];
        self.tipModel = self.today;
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.collectionView reloadData];
            /// 刷新视图后滚动到当天所在的月份
            NSInteger section = (self.today.year - self.startYear) * 12 + self.today.month - 1;
            [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:section] atScrollPosition:UICollectionViewScrollPositionCenteredVertically animated:NO];
            [self reloadTipView];
            [self.indicatorView removeFromSuperview];
        });
    });
}

- (NSMutableArray *)datesArrayByStartYear:(NSInteger)startYear endYear:(NSInteger)endYear {
    NSMutableArray *dataSource = [NSMutableArray array];
    for (NSUInteger y = startYear; y <= endYear; y++) {
        NSString *yearString = [NSString stringWithFormat:@"%lu", y];
        NSDateFormatter *yearFormatter = [[NSDateFormatter alloc] init];
        yearFormatter.dateFormat = @"yyyy";
        NSDate *yearDate = [yearFormatter dateFromString:yearString];
        /// 获取年份对应的月数
        NSUInteger months = [self.calendar rangeOfUnit:NSCalendarUnitMonth inUnit:NSCalendarUnitYear forDate:yearDate].length;
        NSMutableArray *monthArray = [NSMutableArray array];
        for (NSUInteger m = 1; m <= months; m++) {
            NSString *monthString = [NSString stringWithFormat:@"%lu", m];
            NSString *dateString = [NSString stringWithFormat:@"%lu-%@-01", y, monthString];
            NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
            formatter.dateFormat = @"yyyy-MM-dd";
            NSDate *date = [formatter dateFromString:dateString];
            /// 获取月份对应的天数
            NSUInteger days = [self.calendar rangeOfUnit:NSCalendarUnitDay inUnit:NSCalendarUnitMonth forDate:date].length;
            /// 盘点每月1号对应星期几
            NSInteger week = [self getDayWeekByDate:date];
//                NSLog(@"%lu年%lu月有%lu天, 星期%ld", y, m, days, week);
            NSMutableArray *daysArray = [NSMutableArray array];
            for (NSUInteger d = 1; d <= days; d++) {
                NSString *dayString = [NSString stringWithFormat:@"%lu", d];
                NSString *dayDetailString = [NSString stringWithFormat:@"%@-%@-%@", yearString, monthString, dayString];
                NSDate *dayDetailDate = [formatter dateFromString:dayDetailString];
                /// 判断日期是否是当天
                BOOL isToday = [self isToday:dayDetailDate];
                NSInteger dayDetailWeek = [self getDayWeekByDate:dayDetailDate];
                NSString *dayDetailWeekString = [NSString stringWithFormat:@"%ld", dayDetailWeek];
                TCCalendarDateModel *dayModel = [[TCCalendarDateModel alloc] init];
                dayModel.year = y;
                dayModel.yearString = yearString;
                dayModel.month = m;
                dayModel.monthString = monthString;
                dayModel.day = d;
                dayModel.dayString = dayString;
                dayModel.week = week;
                dayModel.weekString = dayDetailWeekString;
                dayModel.isToday = isToday;
                dayModel.isFirstDay = d == 1;
                dayModel.isLastDay = d== days;
                [daysArray addObject:dayModel];
                
                if (isToday) {
                    self.today = dayModel;
                }
            }
            
            /// 保证每月1号能对应到正确的星期，需要在前面插入空白日期做占位
            for (NSInteger w = 0; w < week; w++) {
                TCCalendarDateModel *emptyDayModel = [[TCCalendarDateModel alloc] init];
                [daysArray insertObject:emptyDayModel atIndex:0];
            }
            
            TCCalendarDateModel *monthModel = [[TCCalendarDateModel alloc] init];
            monthModel.year = y;
            monthModel.month = m;
            monthModel.yearString = yearString;
            monthModel.monthString = monthString;
            monthModel.dates = daysArray;
            [monthArray addObject:monthModel];
        }
        
        TCCalendarDateModel *yearModel = [[TCCalendarDateModel alloc] init];
        yearModel.year = y;
        yearModel.yearString = yearString;
        yearModel.dates = monthArray;
        [dataSource addObject:yearModel];
    }
    return dataSource;
}

/// 将日期以 map 形式保存
- (void)initDateMap {
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSMutableDictionary *dateMap = [NSMutableDictionary dictionary];
        for (TCCalendarDateModel *yearModel in self.dataSource) {
            [dateMap setValue:yearModel forKey:yearModel.yearString];
        }
        self.dateMap = dateMap;
    });
}

- (void)loadMoreDates:(TCCalendarDateModel *)date {
    NSInteger year = date.year;
    if (year == self.startYear + 1) {
        NSInteger startYear = self.startYear - 6;
        NSInteger endYear = self.startYear - 1;
        NSMutableArray *months = [self datesArrayByStartYear:startYear endYear:endYear];
        [self.dataSource insertObjects:months atIndexes:[NSIndexSet indexSetWithIndex:0]];
        
    }
}

- (void)setupUI {
    self.backgroundColor = UIColor.whiteColor;
    
    CGFloat tipViewHeight = 80;
    CGFloat itemSize = self.bounds.size.width / 7;
    
    UIButton *maskView = [UIButton buttonWithType:UIButtonTypeCustom];
    maskView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.2];
    [self addSubview:maskView];
    self.maskView = maskView;
    
    UIView *contentView = [[UIView alloc] initWithFrame:self.bounds];
    contentView.clipsToBounds = true;
    contentView.layer.cornerRadius = 10;
    [self addSubview:contentView];
    self.contentView = contentView;
        
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    layout.minimumInteritemSpacing = 0;
    layout.minimumLineSpacing = 0;
    layout.itemSize = CGSizeMake(itemSize, itemSize);
    UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectMake(0, tipViewHeight, self.bounds.size.width, self.bounds.size.height - tipViewHeight) collectionViewLayout:layout];
    collectionView.delegate = self;
    collectionView.dataSource = self;
    collectionView.backgroundColor = UIColor.whiteColor;
//    collectionView.showsVerticalScrollIndicator = NO;
//    collectionView.contentInset = UIEdgeInsetsMake(50, 0, 0, 0);
    [collectionView registerClass:[TCCalendarCollectionViewCell class] forCellWithReuseIdentifier:@"CalendarCell"];
    [collectionView registerClass:[TCCalendarHeaderView class] forSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CalendarHeaderView"];
    [contentView addSubview:collectionView];
    self.collectionView = collectionView;

    TCCalendarTipView *tipView = [[TCCalendarTipView alloc] initWithFrame:CGRectMake(0, 0, self.bounds.size.width, tipViewHeight)];
    tipView.delegate = self;
    [contentView addSubview:tipView];
    self.tipView = tipView;
    
    UIActivityIndicatorView *indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleMedium];
    indicatorView.center = self.center;
    [indicatorView startAnimating];
    [contentView addSubview:indicatorView];
    self.indicatorView = indicatorView;
    
    self.hidden = YES;
}

/// 设置年份展示视图内容
- (void)reloadTipView {
    self.tipView.textLabel.text = [NSString stringWithFormat:@"%@年", self.tipModel.yearString];
}

- (void)reloadCollectionView {
    [CATransaction setDisableActions:YES];
    [self.collectionView reloadData];
    [CATransaction commit];
}

/// 返回传入日期对应的星期
- (NSInteger)getDayWeekByDate:(NSDate *)date {
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSDateComponents *comps = [calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond|NSCalendarUnitWeekday fromDate:date];
    NSInteger weekday = [comps weekday];
    weekday--;
    if (weekday == 7) {
        /// 因为星期日展示在第一列，所以返回0
        return 0;
    } else {
        return weekday;
    }
}

/// 判断传入日期是否是今天
- (BOOL)isToday:(NSDate *)date {
    NSTimeInterval sourceInterval = [date timeIntervalSince1970];
    NSTimeInterval interval = [[NSDate date] timeIntervalSince1970];
    NSTimeInterval difference = interval - sourceInterval;
    if (difference < 24 * 60 * 60 && difference >= 0) {
        return YES;
    } else {
        return NO;
    }
}

/// 将所有选中状态重置为非选中状态
- (void)clearSelectedStatus {
    
    /// 第一次点击的时候都是非选中状态，不用重置
    if (self.firstIndexPath == nil) {
        return;
    }
    
    for (TCCalendarDateModel *monthModel in self.monthDataSource) {
        for (TCCalendarDateModel *dayModel in monthModel.dates) {
            dayModel.isSelected = NO;
        }
    }
}

/// 设置选中状态
- (void)setSelectedStatus {
    NSIndexPath *bigger;
    NSIndexPath *smaller;
    /// 判断两次点击的日期谁大谁小
    if (self.firstIndexPath.section > self.secondIndexPath.section) {
        bigger = self.firstIndexPath;
        smaller = self.secondIndexPath;
    } else {
        bigger = self.secondIndexPath;
        smaller = self.firstIndexPath;
    }
    
    for (NSInteger i = smaller.section; i <= bigger.section; i++) {
        NSInteger smallerRow;
        NSInteger biggerRow;
        TCCalendarDateModel *monthModel = self.monthDataSource[i];
        if (i == smaller.section && i != bigger.section) {
            /// 如果当前遍历的天是在选中的小月份之中，并且两次选中的天数不在同年同月
            /// 如第一次选择2021年3月1日，第二次选择2021年4月1日
            /// 那么小月份从选中的天到本月最后一天都要被选中
            smallerRow = smaller.item;
            biggerRow = monthModel.dates.count;
        } else if (i == bigger.section && i != smaller.section) {
            /// 如果当前遍历的天是在选中的大月份之中，并且两次选中的天数不在同年同月
            /// 如第一次选择2021年3月1日，第二次选择2021年4月1日
            /// 那么大月份从本月第一天到选中的天都要被选中
            smallerRow = 0;
            biggerRow = bigger.item;
        } else if (i == bigger.section && i == smaller.section) {
            /// 如果两次选中的天数在同年同月
            /// 如第一次选择2021年3月1日，第二次选择2021年3月5日
            /// 那么本月选中的小天到选中的大天都要被选中
            smallerRow = MIN(smaller.item, bigger.item);
            biggerRow = MAX(smaller.item, bigger.item);
        } else {
            /// 如果当前遍历的天是在选中的小月份之中，并且两次选中的天数不在同年同月
            /// 如第一次选择2021年3月1日，第二次选择2021年5月1日
            /// 那么当前遍历的天既不在小月中，也不在大月中，就要整个月都被选中
            smallerRow = 0;
            biggerRow = monthModel.dates.count;
        }
        
        for (NSInteger j = smallerRow; j < biggerRow; j++) {
            TCCalendarDateModel *dayModel = monthModel.dates[j];
            if (dayModel.day) {
                dayModel.isSelected = YES;
            }
        }
    }
}

/// 动画显示
- (void)animateShow {
    self.contentView.transform = CGAffineTransformMakeScale(0.85, 0.85);
    self.alpha = 0;
    [UIView animateWithDuration:0.25 delay:0 usingSpringWithDamping:0.4 initialSpringVelocity:10 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        self.contentView.transform = CGAffineTransformMakeScale(1, 1);
        self.alpha = 1;
    } completion:^(BOOL finished) {
        
    }];
}

/// 动画隐藏
- (void)animateHide {    
    [UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        self.contentView.transform = CGAffineTransformMakeScale(0.85, 0.85);
        self.alpha = 0;
    } completion:^(BOOL finished) {
        /// 如果属性隐藏后移除视图为 YES，则移除，反之只隐藏
        if (self.removeOnHidden) {
            [self removeFromSuperview];
        } else {
            self.hidden = YES;
        }
    }];
}

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return self.monthDataSource.count;
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    TCCalendarDateModel *dateModel = self.monthDataSource[section];
    return dateModel.dates.count;
}

- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    TCCalendarCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"CalendarCell" forIndexPath:indexPath];
    TCCalendarDateModel *monthModel = self.monthDataSource[indexPath.section];
    TCCalendarDateModel *date = monthModel.dates[indexPath.item];
    cell.textLabel.text = date.dayString;
    cell.isToday = date.isToday;
    cell.isSelected = date.isSelected;
    [cell reloadViews];
    
    if (monthModel.month == 11 && date.isLastDay) {
        self.tipModel = monthModel;
        [self reloadTipView];
    }
    
    return cell;
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
    TCCalendarDateModel *dateModel = self.monthDataSource[indexPath.section];
    TCCalendarDateModel *date = dateModel.dates[indexPath.item];
    /// 如果点击的是空白日期占位，则不响应点击
    if (date.day) {
        if (self.isSingle) {
            self.firstIndexPath = indexPath;
            self.startDate = date;
            [self clearSelectedStatus];
            date.isSelected = YES;
        } else {
            self.isFirstSelect = !self.isFirstSelect;
            
            if (self.isFirstSelect) {
                [self clearSelectedStatus];
                self.firstIndexPath = indexPath;
                self.startDate = date;
                self.secondIndexPath = nil;
                self.endDate = nil;
            } else {
                self.secondIndexPath = indexPath;
                self.endDate = date;
                [self setSelectedStatus];
            }
            date.isSelected = YES;
        }
        
        [self reloadCollectionView];
    }
}

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
    TCCalendarHeaderView *headerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"CalendarHeaderView" forIndexPath:indexPath];
    TCCalendarDateModel *monthModel = self.monthDataSource[indexPath.section];
    headerView.textLabel.text = [NSString stringWithFormat:@"%@月", monthModel.monthString];
//    [self loadMoreDates:monthModel];
    return headerView;
}

- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout referenceSizeForHeaderInSection:(NSInteger)section {
    return CGSizeMake(self.bounds.size.width, 60);
}

- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath {
    TCCalendarDateModel *monthModel = self.monthDataSource[indexPath.section];
    TCCalendarDateModel *date = monthModel.dates[indexPath.item];
    if (date.month == 11 && date.isLastDay) {
        NSInteger nextYear = monthModel.year + 1;
        NSString *nextYearString = [NSString stringWithFormat:@"%ld", nextYear];
        TCCalendarDateModel *nextYearModel = [self.dateMap valueForKey:nextYearString];
        self.tipModel = nextYearModel;
        [self reloadTipView];
    }
}

- (void)cancelButtonClicked {
    [self animateHide];
}

- (void)confirmButtonClicked {
    [self animateHide];
    /// 根据是多选还是单选来响应对应的回调
    if (self.isSingle) {
        if (_delegate && [_delegate respondsToSelector:@selector(selectedDurationDateWithDate:)]) {
            [_delegate selectedDurationDateWithDate:self.startDate];
        }
    } else {
        if (_delegate && [_delegate respondsToSelector:@selector(selectedDurationDateWithStartDate:endDate:)]) {
            [_delegate selectedDurationDateWithStartDate:self.startDate endDate:self.endDate];
        }
    }
}

- (void)previousButtonClicked:(UIButton *)button textLabel:(UILabel *)textLabel {
//    if (self.tipModel.year == self.startYear) {
//        return;
//    }
//
//    NSInteger previousYear = self.tipModel.year - 1;
//    NSString *previousYearString = [NSString stringWithFormat:@"%ld", previousYear];
//    TCCalendarDateModel *previousYearModel = [self.dateMap valueForKey:previousYearString];
//    self.tipModel = previousYearModel;
//    NSInteger section = (self.tipModel.year - self.startYear) * 12;
//    [self.collectionView scrollToItemAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:section] atScrollPosition:UICollectionViewScrollPositionTop animated:YES];
}

@end
